package models

import java.util.UUID

import org.joda.time.DateTime
import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.functional.syntax._

/**
  * Created by xiaof on 2016/7/25.
  */

case class User(uuid: Option[UUID],
                name: String,
                passwd: String,
                email: String,
                isValid: Option[Boolean],
                createTime: Option[DateTime],
                updateTime: Option[DateTime])

object User {
  //implicit val userFormat = Json.format[User]
  implicit object UserIdentity extends Identity[User,UUID]{
    val name: String ="_id"

    override def next: UUID = UUID.randomUUID()

    override def of(entity: User): Option[UUID] = entity.uuid

    override def set(entity: User, id: UUID): User = entity.copy(uuid=Option(id))

    override def clear(entity: User): User = entity.copy(uuid=None)
  }

  implicit object userWrites extends OWrites[User] {
    def writes(user: User): JsObject = Json.obj(
      "_id" -> user.uuid,
      "name" -> user.name,
      "passwd" -> user.passwd,
      "email" -> user.email,
      "isValid" -> user.isValid.fold(false)(isvalid=>isvalid),
      "createTime" -> user.createTime.fold(new DateTime().getMillis)(_.getMillis),
      "updateTime" -> user.updateTime.fold(new DateTime().getMillis)(_.getMillis))
  }

  implicit object userReads extends Reads[User] {
    def reads(json: JsValue): JsResult[User] = json match {
      case obj: JsObject => try {
        val uuid = (obj \ "_id").asOpt[UUID]
        val name = (obj \ "name").as[String]
        val passwd = (obj \ "passwd").as[String]
        val email= (obj \ "email").as[String]
        val isValid=(obj \ "isValid").asOpt[Boolean]
        val createTime = (obj \ "createTime").asOpt[DateTime]
        val updateTime = (obj \ "updateTime").asOpt[DateTime]

        JsSuccess(User(uuid, name, passwd, email,isValid,
          createTime.map(new DateTime(_)),
          updateTime.map(new DateTime(_))))

      } catch {
        case cause: Throwable => JsError(cause.getMessage)
      }

      case _ => JsError("expected.jsobject")
    }
  }

}
